#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "base.h"


int main(int argc, char const *argv[])
{
    if(argc != 3){
        printf("usage :%s=s <ip> <port>\n",argv[0]);
    }
    //创建socket
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0){
        perror("socket err");
        return -1;
    }    
  
    //服务端地址:IP:Port
    struct sockaddr_in addr;
    addr.sin_family = AF_INET; //协议族
    addr.sin_port = htons(atoi(argv[2])); //port
    addr.sin_addr.s_addr = inet_addr(argv[1]); //IP地址
    socklen_t addrlen =sizeof(addr);
    //bind 
    if(bind(sockfd,(struct sockaddr *)&addr,addrlen)<0)
    {
        perror("bind err");
        close(sockfd);
        return -1;
    }
    //监听listen
    if(listen(sockfd,5)< 0){
        perror("listen err");
        close(sockfd);
        return -1;
    }
    printf("waiting client connect......\n");

    //响应连接
    struct sockaddr_in client_addr;
    socklen_t client_addrlen;
    int clientfd = accept(sockfd,(struct sockaddr*)&client_addr,&client_addrlen);   
    if(clientfd < 0){
        perror("accept err");
        close(sockfd);
        return -1;
    }
    printf("new connect comming\n");
    //判断文件是否存在
    int length=0;
    if((length=recv_header(clientfd))<0){
        perror("recv_header err");
        close(sockfd);
        return -1;
    }
    printf("length:%d\n",length);
    //接收消息体
    char buffer[256]={0};
    recv(clientfd,buffer,length,0);

    //反序列化
    struct C2S_filename file;
    unserialize_filename(&file,buffer);
    printf("filename:%s\n",file.filename);

    struct S2C_fileinfo info;
    struct stat st;
    //打开文件
    int fd=open(file.filename,O_RDONLY);
    if (fd<0)
    {
        perror("open file err");
        info.size = -1;
    }
    else{
        lstat(file.filename,&st);
        info.size=st.st_size;
    }
    info.type=2;

    //向客户端发送文件大小
    memset(buffer,sizeof(buffer),0);
    //序列化
    length=serialize_fileinfo(buffer,(void*)&info);
    //消除粘包
    char* buftosend = addlength(buffer,length);
    //发送
    send(clientfd,buftosend,length+sizeof(int),0);
    free_buftosend(&buftosend);

    struct C2S_loadinfo load;
    struct S2C_file_block block;
    block.type = 4;

    while(info.size>0){
        memset(buffer,sizeof(buffer),0);
        if((length=recv_header(clientfd))<0){
            perror("recv_header err");
            close(sockfd);
            return -1;
        }
        //接收消息体
        recv(clientfd,buffer,length,0);

        //反序列化
        unserialize_loadinfo(&load,buffer);
        off_t offset = load.offset;
        if(offset>=st.st_size){
            break;
        }
        //定位
        lseek(fd,offset,SEEK_SET);
        memset(buffer,sizeof(buffer),0);
        block.offset=offset;
        int len_content = read(fd,buffer,load.block_size);
        strncpy(block.content,buffer,len_content);
        //序列化
        length=serialize_fileblock(buffer,&block,len_content);
        //消除粘包
        buftosend = addlength(buffer,length);
        //发送
        send(clientfd,buftosend,length+sizeof(int),0);
        free_buftosend(&buftosend);
    }
    
    close(fd);
    close(clientfd); //关闭连接的客户端的socket
    close(sockfd); //关闭服务端的socket
    return 0;
}